package com.uuah.server.config.spring.parsers.delegate;

import java.util.Map;

import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;

import com.uuah.server.config.spring.UuahHierarchicalBeanDefinitionParserDelegate;
import com.uuah.server.config.spring.parsers.IUuahDefinitionParser;
import com.uuah.server.config.spring.parsers.IUuahDefinitionParserConfiguration;
import com.uuah.server.config.spring.parsers.PostProcessor;
import com.uuah.server.config.spring.parsers.PreProcessor;
import com.uuah.server.config.spring.parsers.assembly.configuration.IValueMap;
import com.uuah.server.config.spring.parsers.generic.AutoIdUtils;
import com.uuah.utils.ArrayUtils;

/**
 * This allows a definition parsers to be dynamically represented by different
 * definition parsers, depending on the context. For example, a single model may
 * be defined across file - the first use defines the model and subsequent uses
 * extend it (for this particular case, see {@link InheritDefinitionParser}).
 * 
 * <p>
 * Note that the sub-parsers must be consistent. That includes matching the same
 * schema, for example.
 * </p>
 */
public abstract class AbstractDelegatingDefinitionParser extends
		AbstractBeanDefinitionParser implements IUuahDefinitionParser {

	private IUuahDefinitionParser[] delegates;

	protected AbstractDelegatingDefinitionParser() {
		this(new IUuahDefinitionParser[0]);
	}

	protected AbstractDelegatingDefinitionParser(IUuahDefinitionParser[] delegates) {
		this.delegates = delegates;
		addBeanFlag(UuahHierarchicalBeanDefinitionParserDelegate.UUAH_FORCE_RECURSE);
	}

	protected AbstractBeanDefinition parseInternal(Element element,
			ParserContext parserContext) {
		return uuahParse(element, parserContext);
	}

	protected IUuahDefinitionParserConfiguration addDelegate(
			IUuahDefinitionParser delegate) {
		delegates = (IUuahDefinitionParser[]) ArrayUtils.add(delegates, delegate);
		return delegate;
	}

	protected int size() {
		return delegates.length;
	}

	protected IUuahDefinitionParser getDelegate(int index) {
		return delegates[index];
	}

	public IUuahDefinitionParserConfiguration registerPreProcessor(
			PreProcessor preProcessor) {
		for (int i = 0; i < delegates.length; ++i) {
			delegates[i].registerPreProcessor(preProcessor);
		}
		return this;
	}

	public IUuahDefinitionParserConfiguration registerPostProcessor(
			PostProcessor postProcessor) {
		for (int i = 0; i < delegates.length; ++i) {
			delegates[i].registerPostProcessor(postProcessor);
		}
		return this;
	}

	public IUuahDefinitionParserConfiguration addReference(String propertyName) {
		for (int i = 0; i < delegates.length; ++i) {
			delegates[i].addReference(propertyName);
		}
		return this;
	}

	public IUuahDefinitionParserConfiguration addMapping(String propertyName,
			Map mappings) {
		for (int i = 0; i < delegates.length; ++i) {
			delegates[i].addMapping(propertyName, mappings);
		}
		return this;
	}

	public IUuahDefinitionParserConfiguration addMapping(String propertyName,
			String mappings) {
		for (int i = 0; i < delegates.length; ++i) {
			delegates[i].addMapping(propertyName, mappings);
		}
		return this;
	}

	public IUuahDefinitionParserConfiguration addMapping(String propertyName,
			IValueMap mappings) {
		for (int i = 0; i < delegates.length; ++i) {
			delegates[i].addMapping(propertyName, mappings);
		}
		return this;
	}

	public IUuahDefinitionParserConfiguration addAlias(String alias,
			String propertyName) {
		for (int i = 0; i < delegates.length; ++i) {
			delegates[i].addAlias(alias, propertyName);
		}
		return this;
	}

	public IUuahDefinitionParserConfiguration addCollection(String propertyName) {
		for (int i = 0; i < delegates.length; ++i) {
			delegates[i].addCollection(propertyName);
		}
		return this;
	}

	public IUuahDefinitionParserConfiguration addIgnored(String propertyName) {
		for (int i = 0; i < delegates.length; ++i) {
			delegates[i].addIgnored(propertyName);
		}
		return this;
	}

	public IUuahDefinitionParserConfiguration removeIgnored(String propertyName) {
		for (int i = 0; i < delegates.length; ++i) {
			delegates[i].removeIgnored(propertyName);
		}
		return this;
	}

	public IUuahDefinitionParserConfiguration setIgnoredDefault(boolean ignoreAll) {
		for (int i = 0; i < delegates.length; ++i) {
			delegates[i].setIgnoredDefault(ignoreAll);
		}
		return this;
	}

	public String getBeanName(Element element) {
		return AutoIdUtils.getUniqueName(element, "delegate");
	}

	public IUuahDefinitionParserConfiguration addBeanFlag(String flag) {
		for (int i = 0; i < delegates.length; ++i) {
			delegates[i].addBeanFlag(flag);
		}
		return this;
	}

}